package com.tanhua.server;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.PageUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.itheima.commons.utils.Constants;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.dubbo.api.CommentsApi;
import com.tanhua.dubbo.api.FriendApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VideoApi;
import com.tanhua.interceptor.UserHolder;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.enums.CommentType;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.FocusUser;
import com.tanhua.model.mongo.Video;
import com.tanhua.model.vo.CommentVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VideoVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SmallVideoService {
    @DubboReference
    private VideoApi videoApi;
    @Autowired
    private FastFileStorageClient fastFileStorageClient;
    @Autowired
    private FdfsWebServer fdfsWebServer;
    @Autowired
    private OssTemplate ossTemplate;
    //    public final String http = fdfsWebServer.getWebServerUrl();
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @DubboReference
    private UserInfoApi userInfoApi;
    @DubboReference
    private CommentsApi commentsApi;
    @DubboReference
    private FriendApi friendApi;
    @Autowired
    private HuanXinTemplate huanXinTemplate;

    /**
     * 保存视频和图片
     *
     * @param videoThumbnail
     * @param videoFile
     */
    public void saveVideos(MultipartFile videoThumbnail, MultipartFile videoFile) throws IOException {
        //nginx代理IP
        String http = fdfsWebServer.getWebServerUrl();
        //上传视频到fastDFS
        StorePath storePath = fastFileStorageClient.uploadFile(
                videoFile.getInputStream(),
                videoFile.getSize(),
                FileNameUtil.extName(videoFile.getOriginalFilename()),
                null);
        //获取全路径，/group/...
        String fullPath = storePath.getFullPath();
        String videoURL = http + fullPath;

        //上传封面到Oss
        String imgURL = ossTemplate.upload(
                videoThumbnail.getOriginalFilename(),
                videoThumbnail.getInputStream()
        );
        log.info("Video：" + videoURL + "/nImg：" + imgURL);
        //保存URL到数据库
        Video video = new Video();
        video.setPicUrl(imgURL);
        video.setVideoUrl(videoURL);
        video.setUserId(UserHolder.getUserId());
        video.setText("探花小视频独家赞助");
        videoApi.save(video);

    }

    /**
     * 小视频列表
     */
    public PageResult queryVideoList(Integer page, Integer pagesize) {
        //根据Redis推荐查询视频列表
        String key = Constants.VIDEOS_RECOMMEND + UserHolder.getUserId();
        String vidStr = redisTemplate.opsForValue().get(key);
        String[] vids = StringUtils.split(vidStr, ",");
        List<Video> videos;

        int totalPage = 0;
        if (vids != null) {
            List<Long> list = Arrays.stream(vids).map(Long::parseLong).collect(Collectors.toList());
            totalPage = PageUtil.totalPage(list.size(), pagesize);
            if (totalPage < page) {
                videos = videoApi.getByVids(list, page, pagesize);
            } else {
                videos = videoApi.queryVideoList(page - totalPage, pagesize);
            }
        } else {
            videos = videoApi.queryVideoList(page - totalPage, pagesize);
        }
        if (videos == null) {
            return new PageResult();
        }
        //获取用户ids
        List<Long> userId = CollUtil.getFieldValues(videos, "userId", Long.class);
        //查询哟用户详情
        Map<Long, UserInfo> infoMap = userInfoApi.getByIds(userId, null);
        String k = Constants.FOCUS_USER + UserHolder.getUserId();
        String k2 = Constants.VIDEO_LIKE_HASHKEY + UserHolder.getUserId();
        List<VideoVo> videoVoList = videos.stream().map(video -> {
            UserInfo userInfo = infoMap.get(video.getUserId());
            if (userInfo != null) {
                String h = video.getUserId().toString();
                VideoVo videoVo = VideoVo.init(userInfo, video);
                //String key = Constants.VIDEO_LIKE_HASHKEY + userId.toString();
                //        String hashKey = videoUserId.toString();
                //        redisTemplate.opsForHash().put(key, hashKey, "1");
                if (redisTemplate.opsForHash().hasKey(k, h)) {
                    videoVo.setHasFocus(1);
                }
                if (redisTemplate.opsForHash().hasKey(k2, h)) {
                    videoVo.setHasLiked(1);
                }
                return videoVo;
            }
            return null;
        }).filter(Objects::nonNull).collect(Collectors.toList());

        return new PageResult(page, pagesize, 0L, videoVoList);
    }

    /**
     * 关注用户
     * @param followUserId 用户id
     */
    public void userFocus(Long followUserId) {
        Long userId = UserHolder.getUserId();
        //查询用户是否已经关注
        Boolean aBoolean = videoApi.exit(userId, followUserId);
        if (aBoolean) {
            return;
        }

        FocusUser focusUser = new FocusUser();
        focusUser.setUserId(userId);
        focusUser.setFollowUserId(followUserId);
        focusUser.setCreated(System.currentTimeMillis());
        videoApi.saveFollowUser(focusUser);

        //保存到Redis中
        String key = Constants.FOCUS_USER + userId.toString();
        String hashKey = followUserId.toString();
        redisTemplate.opsForHash().put(key, hashKey, "1");

        //如果相互关注，添加好友
        Boolean Boolean = videoApi.exit(followUserId, userId);
        if (Boolean) {
            friendApi.contacts(userId, followUserId);
            huanXinTemplate.addContact(Constants.HX_USER_PREFIX + userId, Constants.HX_USER_PREFIX + followUserId);
        }
    }

    /**
     * 取消关注
     *
     * @param followUserId 用户id
     */
    public void userUnFocus(Long followUserId) {
        Long userId = UserHolder.getUserId();
        Boolean aBoolean = videoApi.exit(userId, followUserId);
        if (aBoolean) {
            videoApi.deleteFollowUser(userId, followUserId);
        }
        //保存到Redis中
        String key = Constants.FOCUS_USER + userId.toString();
        String hashKey = followUserId.toString();
        redisTemplate.opsForHash().delete(key, hashKey);

        //如果相互关注，取消
        Boolean Boolean = videoApi.exit(followUserId, userId);
        if (Boolean) {
            friendApi.unContactsTo(userId, followUserId);
            huanXinTemplate.deleteContact(Constants.HX_USER_PREFIX + userId, Constants.HX_USER_PREFIX + followUserId);
        }
    }

    public void like(String videoId) {
        Long userId = UserHolder.getUserId();
//
        Video video = videoApi.getById(videoId);
        Long videoUserId = video.getUserId();
        videoApi.updateLike(videoId, 1);
//
        String key = Constants.VIDEO_LIKE_HASHKEY + userId.toString();
        String hashKey = videoUserId.toString();
        redisTemplate.opsForHash().put(key, hashKey, "1");
    }

    public void dislike(String videoId) {
        Long userId = UserHolder.getUserId();
//
        Video video = videoApi.getById(videoId);
        Long videoUserId = video.getUserId();
        videoApi.updateLike(videoId, -1);
//
        String key = Constants.VIDEO_LIKE_HASHKEY + userId.toString();
        String hashKey = videoUserId.toString();
        redisTemplate.opsForHash().delete(key, hashKey);
    }

    public void addComments(String id, String comment) {
        Video video = videoApi.getById(id);
        Comment comment1 = new Comment();
        comment1.setPublishId(new ObjectId(id));
        comment1.setCommentType(CommentType.VIDEOCOMMENT.getType());
        comment1.setContent(comment);
        comment1.setCreated(System.currentTimeMillis());
        comment1.setUserId(UserHolder.getUserId());
        comment1.setPublishUserId(video.getUserId());
        comment1.setLikeCount(0);

        commentsApi.saveComments(comment1);
    }

    public PageResult getComments(String id, Integer page, Integer pagesize) {
        List<Comment> commentList = commentsApi.findComments(id, CommentType.VIDEOCOMMENT, page, pagesize);
        List<Long> userId = CollUtil.getFieldValues(commentList, "userId", Long.class);

        Map<Long, UserInfo> userInfoMap = userInfoApi.getByIds(userId, null);
        String key = Constants.VIDEOS_COMMENTS_LIKE + UserHolder.getUserId();
        List<CommentVo> commentVos = commentList.stream().map(comment -> {
            UserInfo userInfo = userInfoMap.get(comment.getUserId());
            if (userInfo != null) {
                CommentVo commentVo = CommentVo.init(userInfo, comment);
                if (redisTemplate.opsForHash().hasKey(key, comment.getId().toHexString())) {
                    commentVo.setHasLiked(1);
                }
                return commentVo;
            }
            return null;
        }).filter(Objects::nonNull).collect(Collectors.toList());

        int count = commentVos.size();
        return new PageResult(page, pagesize, (long) count, commentVos);
    }

    public void likeComments(Long userId, String id) {
        commentsApi.updateCommentsLike(id, 1);
        String key = Constants.VIDEOS_COMMENTS_LIKE + userId;
        redisTemplate.opsForHash().put(key, id, "1");
        commentsApi.updateCommentsLike(id, 1);
    }

    public void dislikeComments(Long userId, String id) {
        commentsApi.updateCommentsLike(id, 1);
        String key = Constants.VIDEOS_COMMENTS_LIKE + userId;
        redisTemplate.opsForHash().delete(key, id);
        commentsApi.updateCommentsLike(id, -1);
    }
}
